package youleche.com.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import youleche.com.business.BUser;
import youleche.com.caches.CacheFactory;
import youleche.com.common.ParamConfigParameters;
import youleche.com.factory.MLLogFactory;
import youleche.com.model.MPagelimit;
import youleche.com.model.MUser;
import youleche.com.util.AESEncryptAndDecrypt;
import youleche.com.util.EscapeAndUnescapeUtil;
import youleche.com.util.UnicodeUtil;

/**
 * 拦截器
 * @author Administrator
 *
 */
public class UrlFilter implements Filter {

	/**
	 * 不用检查的URL
	 */
	private List<String> noCheckURLList = new ArrayList<String>();
	/**
	 * 过滤不通过返回的页面
	 */
	private String redirectURL = null;
	/**
	 * Session秘钥
	 */
	private String sessionKey = null;
	
	/**
	 * 用户名
	 */
	private String userName = "";

	/**
	 * destory
	 */
	public void destroy() {
	}

	/**
	 * Filter初始化
	 */
	public void init(FilterConfig filterConfig) throws ServletException {
		/**
		 * 暂时做成配置，后面从数据库里面做
		 */
		redirectURL = filterConfig.getInitParameter("redirectURL");
		sessionKey = filterConfig.getInitParameter("sessionKey");
		String noCheckURLListStr = filterConfig.getInitParameter("noCheckURLList");
		if(noCheckURLListStr!=null){
			StringTokenizer st = new StringTokenizer(noCheckURLListStr, ";");
			noCheckURLList.clear();
			while(st.hasMoreTokens()){
				noCheckURLList.add(st.nextToken());
			}
		}
	}

	/**
	 * 拦截方法
	 */
	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		request.setCharacterEncoding("UTF-8");
		if(!this.filterRequest(request)){
			response.sendRedirect(redirectURL);
			return;
		}
			
		chain.doFilter(request, response);
	}

	/**
	 * 过滤请求
	 * @param servletRequest
	 * @return false -不成功，调回首页
	 */
	private boolean filterRequest(HttpServletRequest request){
		
		String uri = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo());
		//当前页面是否需要过滤
		if(this.isNotCheckFile(uri)){
			return true;
		}

		//当页面的权限是激活2-用户访问，3-管理员，4-开发人员，5超管人员时需要校验cookie和session
		//判断当前页面的权限
		int pagelimit = this.getPagelimitByPageUrl(uri);
		if(uri.contains(".jsp") || uri.contains(".do")){
			//MLLogFactory.accLog("页面权限等级(2-用户访问，3-管理员，4-开发人员，5超管人员):" + pagelimit, "页面权限", uri, request.getRemoteAddr());
		}
		///pagelimit==0表示没有该页面  可以直接进行访问
		if(pagelimit == 0){
			return true;
		}
		
		if(pagelimit == 2 || pagelimit == 4 || pagelimit == 5 || pagelimit == 3 || pagelimit == 6){
			//校验cookie和session
			if(!this.checkCookies(request)){
				MLLogFactory.accLog("cookie校验不通过", "页面权限", uri, request.getRemoteAddr());
				return false;
			}
			
			if(!this.checkSessions(request)){
				MLLogFactory.accLog("Session校验不通过", "校验session", uri, request.getRemoteAddr());
				return false;
			}
			
			//cookie和session通过后判断用户的权限是否达到页面的权限
			if(!this.checkUserLimitDayuOrDengyuPageLimit(request, pagelimit)){
				MLLogFactory.accLog("权限不足!", "页面权限", uri, request.getRemoteAddr());
				return false;
			}
		}
		
		return true;
	}
	
	/**
	 * 用户访问页面的权限是否大于等于页面的权限
	 * @param pagelimit 页面权限
	 * @return true -用户访问页面的权限大于等于页面的权限
	 */
	private boolean checkUserLimitDayuOrDengyuPageLimit(HttpServletRequest request, int pagelimit){
		BUser handler = new BUser();
		try {
			MUser user = handler.getUserByUserName(userName);
			String userLimit = user.getA3();
			int limit = Integer.parseInt(userLimit);
			if(limit >= pagelimit){
				return true;
			}			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 不需校验的过滤请求
	 * @param uri 页面路径
	 * @return true-是不需要校验的
	 */
	private boolean isNotCheckFile(String uri){
		if(uri.contains("/image/")
				|| uri.contains("/js/")
				|| uri.contains("/css/") 
				|| uri.contains("/bootstrap-select/")){
			return true;
		}
		
		return false;
	}

	/**
	 * 校验Cookie
	 * @param request 请求对象
	 * @return 返回是否校验成功（true-成功）
	 */
	private boolean checkCookies(HttpServletRequest request){
		Cookie[] cookies = request.getCookies();
		if(cookies == null || cookies.length == 0 ||cookies.length == 1){
			userName = "";
			return false;
		}
		
		for(int i=0 ;i<cookies.length;i++){
			if(cookies[i].getName().equals("youleche.u")){
				String cookieVlaue = cookies[i].getValue();
				//String cookieJson = EscapeAndUnescapeUtil.unescape(cookieVlaue);
				userName = cookieVlaue;
				break;
			}
		}
		
		return !"".equals(userName);
	}
	
	/**
	 * 校验session
	 * @param request 请求对象
	 * @return 返回是否校验成功（true-成功）
	 */
	private boolean checkSessions(HttpServletRequest request){
		try{
			HttpSession session = request.getSession(false);
			
			sessionKey = (String) session.getAttribute(userName);
			if(sessionKey==null || "".equals(sessionKey)){
				return false;
			}
			
			ParamConfigParameters paramConfig = new ParamConfigParameters();
			String loginCode_KEY = paramConfig.getParameter("loginCode_KEY");
			sessionKey = AESEncryptAndDecrypt.decrypt(sessionKey, loginCode_KEY);		
	
			if(!sessionKey.contains("^")){
				return false;
			}
			
			String name = sessionKey.split("\\^")[0];
			if(UnicodeUtil.isContainsChinese(name)){
				name = java.net.URLEncoder.encode(name,"utf-8");
			}
			
			if("".equals(name) || !userName.equals(name)){
				return false;
			}		
			
			return true;
		}catch(Exception e){
			MLLogFactory.accLog("校验session 出现异常", "校验session 出现异常", e.getMessage(), request.getRemoteAddr());
			return false;
		}
	}
	
	/**
	 * 根据页面路径获取页面的权限
	 * @param url
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private int getPagelimitByPageUrl(String url){
		int pagelimit = 0;

		if(url.contains(".jsp") || url.contains(".do")){	
			try {
				@SuppressWarnings("static-access")
				List<MPagelimit> nodes = (List<MPagelimit>) CacheFactory.getPageLimitCache().getCache();
				for (MPagelimit node : nodes) {
					if(url.equals(node.getPageUrl())){
						pagelimit = Integer.parseInt(node.getLimitLevel());
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}			
		}
		
		return pagelimit;
	}
}
